package kioschool.controller
{
	import flash.display.*;
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.geom.*;
	import flash.text.*;
	import flash.utils.Dictionary;
	
	import kioschool.model.AbstractStep;
	import kioschool.view.IStepView;
	import kioschool.view.controls.ICommentPanel;
	import kioschool.view.controls.IControlsFactory;
	import kioschool.view.controls.INavigationPanel;
	import kioschool.view.controls.IPerspective;
	import kioschool.view.controls.IRegimePanel;
	import kioschool.view.controlsimpl.DefaultControlsFactory;
	import kioschool.view.controlsimpl.DefaultPerspective;
	import kioschool.view.controlsimpl.DefaultRegimePanelView;
	import kioschool.view.layout.ComponentLayout;
	
	/**
	 * Главный контроллер платформы
	 * Управляет переходами между шагами
	 * Сингельтон
	 * 
	 * @author Akimushkin Vasiliy
	 * 
	 */ 
	public class PrimaryController
	{
		/**
		 * Режим демонстрации - отображение применения алгоритма к данным <br/>
		 * Все действия выполняются без участия пользователя
		 */ 
		public static const REGIME_DEMO:int = 1;
		
		/**
		 * Режим тренировки - изменения производятся пользователем в рамках одного шага <br/>
		 * При неверной операции - сообщение об ошибке и отсутствие перехода на следующий шаг
		 */ 
		public static const REGIME_TRAINING:int = 2;
		
		/**
		 * Режим контроля - весь алгоритм выполняется пользователем <br/>
		 * В конце - отчет об ошибках
		 */ 
		public static const REGIME_CONTROL:int = 3;
		
		/**
		 * Сингельтон
		 */
		private static var _instance:PrimaryController;
		
		/**
		 * Получает экземпляр
		 */ 
		public static function get instance():PrimaryController {
			if(PrimaryController._instance == null)
				PrimaryController._instance=new PrimaryController(new PrivateClass( ));
			return _instance;
		}
		
		
		/**
		 * Текущий режим платформы
		 */ 
		private var _currentRegime:int;
		
		/**
		 * Массив пройденных шагов
		 */ 
		private var _stepArray:Array = new Array();
		
		/**
		 * Панель смены режимов
		 */ 
		private var _regimePanel:IRegimePanel;
		
		/**
		 * Панель навигации
		 */ 
		private var _navigationPanel:INavigationPanel;
		
		/**
		 * Рабочая область
		 */ 
		private var _workspace:DisplayObjectContainer;
		
		/**
		 * Панель комментариев
		 */ 
		private var _commentPanel:ICommentPanel;
		
		/**
		 * Вторичный контроллер - уникальный для каждого манипулятора
		 */ 
		private var _secondaryController:ISecondaryController;
		
		/**
		 * История ошибок дял режима контроля 
		 */ 
		private var errorsHistory:Array = [];
		
		/**
		 * Конструктор, скрытый для всех вне данного файла
		 */ 
		public function PrimaryController(pvt:PrivateClass){		
		}
		
		/**
		 * Инициализация контроллера - выполняется один раз при запуске манипулятора!
		 * 
		 */ 
		public function init(stage:Stage, width:int, height:int, secondaryController:ISecondaryController, controlsFactory:IControlsFactory=null, perspective:IPerspective=null):void{
			
			_secondaryController = secondaryController;
			controlsFactory=(controlsFactory==null)?new DefaultControlsFactory():controlsFactory;
			perspective=(perspective==null)?new DefaultPerspective():perspective;
			
			_regimePanel = controlsFactory.createRegimePanel();
			_navigationPanel = controlsFactory.createNavigationPanel();
			_workspace = controlsFactory.createWorkspace();
			_commentPanel = controlsFactory.createCommentPanel();	
			
			perspective.placeComponents(stage,width,height,_regimePanel,_navigationPanel,_commentPanel,_workspace);
					
			initController();
			
			regime=REGIME_DEMO;
			_commentPanel.greeting=_secondaryController.greeting;
		}
		
		
		/**
		 * Генерация условия задачи
		 */ 
		public function initController():void {
			errorsHistory = [];
			_secondaryController.init();
			_stepArray = new Array();
			_stepArray.push(_secondaryController.firstStep);
			updateStep();
			_commentPanel.greeting=_secondaryController.greeting;
		}
		
		/**
		 * Получает текущий шаг
		 */ 
		public function get currentStep():AbstractStep{
			if(_stepArray.length==0)
				return null;
			return _stepArray[_stepArray.length-1];
		}
		
		/**
		 * Возвращает текущий режим
		 */ 
		public function get regime():int {
			return _currentRegime;
		}
		
		/**
		 * Устанавливает текущий режим
		 */ 
		public function set regime(newRegime:int):void {
			if (newRegime == regime)
				return;
			var last:int = _currentRegime;
			_currentRegime = newRegime;
			_regimePanel.regimeChanged(regime);
			_navigationPanel.regimeChanged(regime);
			_secondaryController.regimeChanged(regime);
			if (newRegime == REGIME_CONTROL || last == REGIME_CONTROL) {				
				initController(); //Инициализация нового условия (перезапуск контроллера)
			} else {
				currentStep.restore();
				updateStep();
			}
			if(newRegime!=REGIME_DEMO)
				enableAnyAction(_workspace, true);
		}
		
		public function updateStep():void {
			var view:IStepView = currentStep.getView();
			
			clearWorkspace();
			view.draw(_workspace);
			
			//хитрый hack, размер области определяет первый потомок
			_workspace.width=_workspace.getChildAt(0).width+_workspace.getChildAt(0).x;
			_workspace.height=_workspace.getChildAt(0).height+_workspace.getChildAt(0).y;
			
			_navigationPanel.stepChanged(_stepArray.length<=1,currentStep);
			
			if(regime==REGIME_CONTROL)
				_commentPanel.comment=_secondaryController.greeting;
			else
				_commentPanel.comment=currentStep.comment;
			
			if(regime==REGIME_DEMO){
				enableAnyAction(_workspace, false);
			}
		}
		
		/**
		 * Блокирует реакцию на действия пользователя
		 */ 
		private function enableAnyAction(container:DisplayObjectContainer, enabled:Boolean):void{
			for(var i:int=0; i<container.numChildren; i++){
				var displayObject:DisplayObject = container.getChildAt(i);
				if(displayObject is InteractiveObject){
					(InteractiveObject(displayObject)).mouseEnabled = enabled;	
				}
				if(displayObject is MovieClip){
					(MovieClip(displayObject)).enabled = enabled;	
				}
				if(displayObject is DisplayObjectContainer){
					enableAnyAction(DisplayObjectContainer(displayObject), enabled);	
				}
			}
		}
		
		/**
		 * Очистка области рисования
		 */ 
		private function clearWorkspace():void {
			while (_workspace.numChildren > 0)
				_workspace.removeChildAt(0);
		}
		
		//Переход между режимами
		public function nextClick():void {
			if (regime == REGIME_DEMO) {
				currentStep.oracle();//Решаем шаг
			} else if (regime==REGIME_TRAINING) {
				if (currentStep.checkInput() != null) {
					_commentPanel.error = currentStep.checkInput();
					return;
				}
			} else if (regime==REGIME_CONTROL) {
				var res:String = currentStep.checkInput();
				if(res != null){
					errorsHistory.push(res);
					currentStep.correct = false;
				}
				trace(errorsHistory.length);
			}
			_stepArray.push(currentStep.next());
			currentStep.update();
			updateStep();
		}
		
		//Событие кнопки Назад
		public function backClick():void {
			currentStep.restore();
			_stepArray.pop();
			currentStep.antiOracle();
			currentStep.update();
			if(!currentStep.correct){
				currentStep.correct=true;
				errorsHistory.pop();
			}
			updateStep();
			
			
		}
		
		public function submitSolution():void {
			var res:Boolean = errorsHistory.length==0 && currentStep.next()==null;
			//TODO and now alert to user a result of submition and send it to server. See temporary solution
			if (res == true)
				_commentPanel.comment = "ОТВЕТ ВЕРНЫЙ!!!!! Результат зафиксирован в журнале";
			else
				_commentPanel.error = "ОТВЕТ Неверный. :( Результат зафиксирован в журнале";
		}
	}
}

/**
 * Скрытый класс, необходим для корректной реализации "Одиночки"
 *  
 * @author Akimushkin Vasiliy 
 */
class PrivateClass{
	public function PrivateClass(){	
	}
}